﻿/*
   Copyright 2012 University of Southampton

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Web.UI.HtmlControls;
using uk.ac.soton.ses.DAL;
using System.Web;
using uk.ac.soton.ses.WebControls;

namespace uk.ac.soton.ses.layouts
{
    public partial class ReportPrintout : LayoutsPageBase
    {
        private readonly static string[] SupportedImageTypes = new string[] {".jpg", ".jpeg", ".png", ".tif"};
        private MaterialsMetadataContext dbcontext;
        private List<int> RequestedParameterIDs = null;
        private List<int> RequestedDataFileIDs = null;
        private string reportTitle = null;
        private string reportDescription = null;
        private bool IsInitialised = false;

        //Requested experiment IDs
        public Dictionary<int,Experiment> RequestedExperiments = null;

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            try
            {
                this.dbcontext = HttpContext.Current.GetMaterialsDBContext();
                this.View_ParameterIFrames.ItemCreated += new RepeaterItemEventHandler(View_ParameterIFrames_ItemCreated);
                this.ProcessQueryString();
                this.PrepareData();
                this.IsInitialised = true;
            }
            catch (Exception)
            {
                HDCSharedWebFunctions.AddErrorLabel("Could not load data", this.PlaceHolder_Messages);
                this.IsInitialised = false;
            }
        }

        private void View_ParameterIFrames_ItemCreated(object sender, RepeaterItemEventArgs e)
        {
            //The iframe needs javascript to set it to the size of its contents
            //Because the iframe has to be runat=server we have to add the onload property manually
            HtmlControl iframe = e.Item.FindControl("ParameterIFrame") as HtmlControl;
            if (iframe != null)
            {
                iframe.Attributes.Add("onload", "javascript:resizeiframetocontents(this);");
            }
        }

        private void PrepareData()
        {
            //If we don't have any requested parameters or data files, we will load from them from the requested experiments (and optionally set the report title)
            if (this.RequestedParameterIDs.Count == 0 && this.RequestedDataFileIDs.Count == 0)
            {
                //Set the report title if we can (we can only really do this if the user has not requested specific parameters and has only asked for one experiment)
                if (string.IsNullOrEmpty(this.reportTitle) && this.RequestedExperiments.Count == 1)
                {
                    this.reportTitle = this.RequestedExperiments.Values.First().Name;
                }

                //Set the report description if we can (we can only really do this if the user has not requested specific parameters and has only asked for one experiment)
                if (string.IsNullOrEmpty(this.reportDescription) && this.RequestedExperiments.Count == 1)
                {
                    this.reportDescription = this.RequestedExperiments.Values.First().Description;
                }

                //Generate a list of parameters and data files to display in the report (if the user has not requested specific parameters, but has requested some experiments)
                foreach (Experiment experiment in this.RequestedExperiments.Values)
                {
                    this.RequestedParameterIDs.AddRange(dbcontext.GetExperimentTopLevelParameters(experiment.ID, false).Select(param => param.ID));
                    this.RequestedDataFileIDs.AddRange(dbcontext.GetExperimentDataFilesByExperimentID(experiment.ID, false).Select(df => df.ID));
                }
            }

           

        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (this.IsInitialised)
            {
                if (!string.IsNullOrEmpty(reportTitle))
                {
                    HtmlGenericControl h1 = new HtmlGenericControl("h1");
                    h1.Attributes.Add("class", "ReportName");
                    this.PlaceHolder_ReportName.Controls.Add(h1);

                    Label lblReportName = new Label();
                    h1.Controls.Add(lblReportName);

                    lblReportName.Text = reportTitle;

                    if (!string.IsNullOrEmpty(reportDescription))
                    {
                        HtmlGenericControl p = new HtmlGenericControl("p");
                        p.Attributes.Add("class", "ReportDescription");
                        this.PlaceHolder_ReportDescription.Controls.Add(p);

                        Label lblReportDescription = new Label();
                        p.Controls.Add(lblReportDescription);

                        lblReportDescription.Text = reportDescription;
                    }
                }

                List<ExperimentParameter> experimentParameters = new List<ExperimentParameter>();
                List<ExperimentParameter> iframeParameters = new List<ExperimentParameter>();
                foreach (int paramid in this.RequestedParameterIDs)
                {
                    ExperimentParameter param = dbcontext.ExperimentParameters.Include("Experiment").FirstOrDefault(p => p.ID == paramid);
                    if (param != null)
                    {
                        if (param.Type.Equals("iframe", StringComparison.OrdinalIgnoreCase))
                        {
                            iframeParameters.Add(param);
                        }
                        else
                        {
                            experimentParameters.Add(param);
                        }
                    }
                }
                
                this.ctlParameterReporting.DataSource = experimentParameters.OrderBy(p => p.Experiment.ID).ThenBy(p => p.Position).ThenBy(p => p.Name);
                this.ctlParameterReporting.DataBind();

                this.View_ParameterIFrames.DataSource = iframeParameters.OrderBy(p => p.Experiment.ID).ThenBy(p => p.Position).ThenBy(p => p.Name);
                this.View_ParameterIFrames.DataBind();

                IEnumerable<ExperimentDataFile> allDataItems =
                    this.RequestedDataFileIDs.Select(id => dbcontext.GetExperimentDataFileByID(id));

                List<ExperimentDataFile> imageDataItems1 = new List<ExperimentDataFile>();
                List<ExperimentDataFile> nonImageDataItems1 = new List<ExperimentDataFile>();

                foreach (ExperimentDataFile dataFile in allDataItems)
                {
                    string ext = new FileInfo(dataFile.Filename).Extension;
                    if (SupportedImageTypes.Contains(ext, StringComparer.OrdinalIgnoreCase))
                    {
                        if (!dataFile.IsDeleted)
                        {
                            imageDataItems1.Add(dataFile);
                        }
                    }
                    else
                    {
                        nonImageDataItems1.Add(dataFile);
                    }
                }

                //IEnumerable<ExperimentDataFile> imageDataItems =
                //     allDataItems
                //    .AsEnumerable() //To use FileInfo, we need the data in memory, not just as an IQueryable
                //    .Where(delegate(ExperimentDataFile file)
                //    {
                //        string ext = new FileInfo(file.Filename).Extension;
                //        return SupportedImageTypes.Contains(ext, StringComparer.OrdinalIgnoreCase) && !file.IsDeleted;
                //    });

                //IEnumerable<ExperimentDataFile> nonImageDataItems =
                //    allDataItems
                //    .AsEnumerable() //To use FileInfo, we need the data in memory, not just as an IQueryable
                //    .Where(file =>
                //    {
                //        string ext = new FileInfo(file.Filename).Extension;
                //        return !SupportedImageTypes.Contains(ext, StringComparer.OrdinalIgnoreCase);
                //    });

                this.DataItemReportingControl.DataSource = imageDataItems1;
                this.DataItemReportingControl.DataBind();

                if (nonImageDataItems1.Count() > 0)
                {
                    this.View_DataFiles.DataSource = nonImageDataItems1;
                    this.View_DataFiles.DataBind();
                    this.Panel_DataFiles.Visible = true;
                }
                else
                {
                    this.Panel_DataFiles.Visible = false;
                }
            }
        }

        private void ProcessQueryString()
        {
            try
            {
                this.reportTitle = Page.Request.QueryString["ReportTitle"];
                this.reportDescription = Page.Request.QueryString["ReportDescription"];

                string[] experimentIDStrings = Page.Request.QueryString.GetValues("ExperimentID") ?? new string[0];
                IEnumerable<int> experimentIDs = experimentIDStrings.Select(id => int.Parse(id)).Distinct();
                this.RequestedExperiments = experimentIDs.Select(id => dbcontext.GetExperimentByID(id)).ToDictionary(exp => exp.ID);// new HashSet<int>(experimentIDs);

                string[] parameterIDStrings = Page.Request.QueryString.GetValues("ParameterID") ?? new string[0];
                IEnumerable<int> parameterIDs = parameterIDStrings.Select(id => int.Parse(id)).Distinct();
                this.RequestedParameterIDs = parameterIDs.ToList();

                string[] datafileIDStrings = Page.Request.QueryString.GetValues("DataFileID") ?? new string[0];
                IEnumerable<int> datafileIDs = datafileIDStrings.Select(id => int.Parse(id)).Distinct();
                this.RequestedDataFileIDs = datafileIDs.ToList();
            }
            catch (Exception ex)
            {
                if (ex is FormatException || ex is OverflowException || ex is ArgumentNullException)
                {
                    HDCSharedWebFunctions.AddErrorLabel("Could not parse ID", this.PlaceHolder_Messages);
                }
                if (ex is NullReferenceException)
                {
                    HDCSharedWebFunctions.AddErrorLabel("Could not find ID", this.PlaceHolder_Messages);
                }
                throw;
            }
        }

        //protected void ParameterList_ItemDataBound(object sender, RepeaterItemEventArgs e)
        //{
        //    ExperimentParameter parameter = (ExperimentParameter)e.Item.DataItem; //Retrieve the parameter we need to bound from the Repeater
        //    ParameterReportingControl parameterList = (ParameterReportingControl)e.Item.FindControl("ParameterReportingControl"); //Find the control that will display the data
        //    parameterList.DataSource = new List<ExperimentParameter> { parameter }; //Set the control's DataSource
        //    parameterList.DataBind(); //Ask the control to DataBind to its new DataSource
        //}

        public override void Dispose()
        {
            base.Dispose();
            if (this.dbcontext != null)
            {
                this.dbcontext.Connection.Close();
                this.dbcontext.Dispose();
            }
        }

    }
}
